from django.db import models
from luffyapi.utils.models import BaseModel

class CourseCategory(BaseModel):
    """
        之前创建了公共模型一堆字段 BaseModel继承就可以获得字段，并在基础上添加新的字段
        课程分类
    """
    name = models.CharField(max_length=64, unique=True, verbose_name="分类名称")
    class Meta:
        db_table = "ly_course_category"
        verbose_name = "课程分类"
        verbose_name_plural = "课程分类"

    def __str__(self):
        return "%s" % self.name


from ckeditor_uploader.fields import RichTextUploadingField
class Course(BaseModel):
    """
    专题课程
    """
    name = models.CharField(max_length=128, verbose_name="课程名称")
    course_img = models.ImageField(upload_to="course", max_length=255, verbose_name="封面图片", blank=True, null=True)
    course_video = models.FileField(upload_to="video",null=True,blank=True,verbose_name="封面视频")
    course_type = (
        (0, '付费课程'),
        (1, 'VIP专享'),
        (2, '学位课程')
    )
    course_type = models.SmallIntegerField(choices=course_type,default=0, verbose_name="付费类型")
    # 使用这个字段的原因  TextField 到时候可以编辑 富编辑器 可以放图片和文字
    brief = RichTextUploadingField(max_length=2048, verbose_name="课程概述", null=True, blank=True)
    level_choices = (
        (0, '初级'),
        (1, '中级'),
        (2, '高级'),
    )
    level = models.SmallIntegerField(choices=level_choices, default=1, verbose_name="难度等级")
    pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True)
    period = models.IntegerField(verbose_name="建议学习周期(day)", default=7)
    # 附件的路径
    attachment_path = models.FileField(max_length=128, verbose_name="课件路径", blank=True, null=True)
    status_choices = (
        (0, '上线'),
        (1, '下线'),
        (2, '预上线'),
    )
    status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="课程状态")
    course_category = models.ForeignKey("CourseCategory", on_delete=models.CASCADE, null=True, blank=True,verbose_name="课程分类")
    students = models.IntegerField(verbose_name="学习人数",default = 0)
    lessons = models.IntegerField(verbose_name="总课时数量",default = 0)
    pub_lessons = models.IntegerField(verbose_name="课时更新数量",default = 0)
    price = models.DecimalField(max_digits=6,decimal_places=2, verbose_name="课程原价",default=0,help_text="如果这里填写价格为0，表示这个课程购买的时候，没有永久有效的购买期限")
    # 外键删除不影响 models.DO_NOTHING
    teacher = models.ForeignKey("Teacher",on_delete=models.DO_NOTHING, null=True, blank=True,verbose_name="授课老师")
    class Meta:
        db_table = "ly_course"
        verbose_name = "专题课程"
        verbose_name_plural = "专题课程"

    def __str__(self):
        return "%s" % self.name

    @property
    def lessons_list(self):
        """展示课程列表页面中 推荐课信息 限制展示4条"""
        data_list = []
        lesson_list = CourseLesson.objects.filter(is_show=True,is_deleted=False,course_id=self.id,is_show_list=True).all()
        #将queryset转化为字典
        for lesson in lesson_list:
            data_list.append({
                "id":lesson.id,
                "name":lesson.name,
                "lession":lesson.lession,
                "free_trail":lesson.free_trail,
            })
        return data_list

    @property
    def level_name(self):
        """让序列化器返回的level_name字段，将对level字段返回的数字转化为对应的中文"""
        return self.level_choices[self.level][1]


    @property
    def brief_html(self):
        """
            对brief中的数据进行转义，将图片等连接地址进行更换，避免请求前端8080:/xxx/xx，后端上传的图片等应该是后端8000:/xxx/xx才对
            所以序列化器 不返回brief ，而是返回 brief_html
        """
        from luffyapi.settings import constants
        html = self.brief.replace('src="/media','src="%s/media'%(constants.SERVER_IMAGE_DOMAIN))
        return html

    def active_list(self):
        """
            获取当前课程参与的所有活动 并判断时间是否在有效期之内,活动大于开始时间，小于结束时间
        """
        from _datetime import datetime
        return self.activeprices.filter(is_show=True,is_deleted=False,active__start_time__lte=datetime.now(),active__end_time__gte=datetime.now()).order_by("-orders","-id")

    @property
    def discount_name(self):
        """如果商品有参与了活动，则返回折扣类型"""
        name = ""
        active_list = self.active_list()    #调用获取当前课程参与活动
        if len(active_list) > 0:
            """当前课程如果有参与到1个以上活动时才有优惠类型"""
            active =active_list[0]  #拿到活动
            name = active.discount.discount_type.name   #通过course的activeprices字段查的结果，在通过discount字段对应表的discount_type，在通过discount_type对应的表拿到name
        return name


    def real_price(self,expire_id=0):
        """课程真实价格"""
        origin_price = self.price
        try:
            #根据不同有效期，获取课程原价
            if expire_id > 0:
                # 查找到CourseExpire 表中
                origin_price = CourseExpire.objects.get(id=expire_id).price
        except CourseExpire.DoesNotExist:
            pass

        #默认真实价格是原价 如果没有参与活动，就代表是原价
        price = origin_price

        active_list = self.active_list()  # 调用获取当前课程参与活动
        if len(active_list) > 0:
            """如果当前课程参与了活动，需要将默认真实价格的原价调整为活动价格"""
            active = active_list[0]  # 拿到活动
            #拿到参与活动的满足优惠价格条件
            condition = active.discount.condition   #通过查CoursePriceDiscount表discount字段 查CourseDiscount表condition字段
            #拿到 优惠公式
            sale = active.discount.sale
            origin_price = float(origin_price)
            if self.price >= condition:
                """逻辑只有 原价 必须大于等于 参与活动的满足优惠价格条件，根据优惠公式 进行优惠计算"""
                if sale== "":
                    """限时免费"""
                    price = 0
                elif sale[0] == "*":
                    """限时折扣"""
                    price = origin_price * float(sale[1:])    #字符串转数字
                elif sale[0] == "-":
                    """限时减免"""
                    price = origin_price - float(sale[1:])
                elif sale[0] == "满":
                    """
                        满减
                        如果只买1个商品，只会满足其中一个优惠选项
                    """
                    # print(sale)  # 满500-80
                    sale_list =  sale.split("\r\n")     #['满500-80', '满400-40', '满300-20', '满200-10']
                    price_list = [] #吧满减满足的价格都放进去，为了选出满减最大的值
                    # 吧满减每一个选项循环中提取条件价格和课程原价进行判断
                    for sale_item in sale_list:
                        item = sale_item[1:]    #去掉满这个字
                        condition_price , condition_sale = item.split('-')  #根据-分隔
                        if origin_price > float(condition_price):
                            price_list.append(float(condition_sale))    #优惠列表 比如满足300 满足满400 和 满500，列表中跳最大的
                    price = origin_price - max(price_list)    #原价 - 满xx = 需要支付的剩下的价格
        return "%.2f"%(price) #返回整数后带2小数点

    @property
    def activity_time(self):
        """计算活动剩余时间"""
        time = 0
        active_list = self.active_list()    #调用获取当前课程参与活动

        if len(active_list) > 0:
            """当前课程如果有参与到1个以上活动时才有优惠类型"""
            from _datetime import datetime
            active = active_list[0]  # 拿到活动
            now_time = datetime.now().timestamp()   #获取现在时间的时间戳
            end_time= active.active.end_time.timestamp()    #活动结束时间的时间戳
            time = end_time - now_time
        return int(time)

    @property
    def expire_list(self):
        """课程有效期选项"""
        # 通过 course_expire 查找到CourseExpire 表中
        expires = self.course_expire.filter(is_show=True,is_deleted=False)
        data = []
        for item in expires:
            data.append({
                "id": item.id,
                "expire_text": item.expire_text,
                "price": item.price
            })
        if self.price > 0:
            """判断是否有永久有效的选项，定义表字段price当等于0就有永久有效的选项"""
            data.append({
                "id": 0,
                "expire_text":"永久有效",
                "price": self.price,
            })
        return data



class Teacher(BaseModel):
    """讲师、导师表"""
    role_choices = (
        (0, '讲师'),
        (1, '导师'),
        (2, '班主任'),
    )
    name = models.CharField(max_length=32, verbose_name="讲师title")
    role = models.SmallIntegerField(choices=role_choices, default=0, verbose_name="讲师身份")
    title = models.CharField(max_length=64, verbose_name="职位、职称")
    signature = models.CharField(max_length=255, verbose_name="导师签名", help_text="导师签名", blank=True, null=True)
    image = models.ImageField(upload_to="teacher", null=True, verbose_name = "讲师头像")
    brief = models.TextField(max_length=1024, verbose_name="讲师描述")

    class Meta:
        db_table = "ly_teacher"
        verbose_name = "讲师导师"
        verbose_name_plural = "讲师导师"

    def __str__(self):
        return "%s" % self.name


class CourseChapter(BaseModel):
    """课程章节"""
    course = models.ForeignKey("Course", related_name='coursechapters', on_delete=models.CASCADE, verbose_name="课程名称")
    chapter = models.SmallIntegerField(verbose_name="属于第几章", default=1)
    name = models.CharField(max_length=128, verbose_name="章节标题")
    summary = models.TextField(verbose_name="章节介绍", blank=True, null=True)
    pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True)

    class Meta:
        db_table = "ly_course_chapter"
        verbose_name = "课程章节"
        verbose_name_plural = "课程章节"

    def __str__(self):
        return "%s:(第%s章)%s" % (self.course, self.chapter, self.name)


class CourseLesson(BaseModel):
    """课程课时"""
    chapter = models.ForeignKey("CourseChapter", related_name='coursesections', on_delete=models.CASCADE,verbose_name="课程章节")
    name = models.CharField(max_length=128,verbose_name = "课时标题")
    section_type_choices = (
        (0, '文档'),
        (1, '练习'),
        (2, '视频')
    )
    section_type = models.SmallIntegerField(default=2, choices=section_type_choices, verbose_name="课时种类")
    section_link = models.CharField(max_length=255, blank=True, null=True, verbose_name="课时链接", help_text = "若是video，填vid,若是文档，填link")
    duration = models.CharField(verbose_name="视频时长", blank=True, null=True, max_length=32)  # 仅在前端展示使用
    pub_date = models.DateTimeField(verbose_name="发布时间", auto_now_add=True)
    free_trail = models.BooleanField(verbose_name="是否可试看", default=False)
    course = models.ForeignKey("Course",related_name="course_lesson",on_delete=models.CASCADE,verbose_name="是否可以试看")
    is_show_list = models.BooleanField(verbose_name="是否推荐到课程列表",default=False)
    lession = models.IntegerField(verbose_name="第几课时")
    class Meta:
        db_table = "ly_course_lesson"
        verbose_name = "课程课时"
        verbose_name_plural = "课程课时"

    def __str__(self):
        return "%s-%s" % (self.chapter, self.name)





"""价格相关的模型"""
class CourseDiscountType(BaseModel):
    """课程优惠类型"""
    name = models.CharField(max_length=32, verbose_name="优惠类型名称")
    remark = models.CharField(max_length=250, blank=True, null=True, verbose_name="备注信息")

    class Meta:
        db_table = "ly_course_discount_type"
        verbose_name = "课程优惠类型"
        verbose_name_plural = "课程优惠类型"

    def __str__(self):
        return "%s" % (self.name)



class CourseDiscount(BaseModel):
    """课程优惠模型"""
    discount_type = models.ForeignKey("CourseDiscountType", on_delete=models.CASCADE, related_name='coursediscounts',
                                      verbose_name="优惠类型")
    condition = models.IntegerField(blank=True, default=0, verbose_name="满足优惠的价格条件",help_text="设置参与优惠的价格门槛，表示商品必须在xx价格以上的时候才参与优惠活动，<br>如果不填，则不设置门槛")
    sale = models.TextField(verbose_name="优惠公式",blank=True,null=True, help_text="""
    不填表示免费；<br>
    *号开头表示折扣价，例如*0.82表示八二折；<br>
    -号开头则表示减免，例如-20表示原价-20；<br>
    如果需要表示满减,则需要使用 原价-优惠价格,例如表示课程价格大于100,优惠10;大于200,优惠20,格式如下:<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;满100-10<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;满200-25<br>
    """)

    class Meta:
        db_table = "ly_course_discount"
        verbose_name = "价格优惠策略"
        verbose_name_plural = "价格优惠策略"

    def __str__(self):
        return "价格优惠:%s,优惠条件:%s,优惠值:%s" % (self.discount_type.name, self.condition, self.sale)



class Activity(BaseModel):
    """优惠活动"""
    name = models.CharField(max_length=150, verbose_name="活动名称")
    start_time = models.DateTimeField(verbose_name="优惠策略的开始时间")
    end_time = models.DateTimeField(verbose_name="优惠策略的结束时间")
    remark = models.CharField(max_length=250, blank=True, null=True, verbose_name="备注信息")

    class Meta:
        db_table = "ly_activity"
        verbose_name="商品活动"
        verbose_name_plural="商品活动"

    def __str__(self):
        return self.name




class CoursePriceDiscount(BaseModel):
    """课程与优惠策略的关系表"""
    course = models.ForeignKey("Course",on_delete=models.CASCADE, related_name="activeprices",verbose_name="课程")
    active = models.ForeignKey("Activity",on_delete=models.DO_NOTHING, related_name="activecourses",verbose_name="活动")
    discount = models.ForeignKey("CourseDiscount",on_delete=models.CASCADE,related_name="discountcourse",verbose_name="优惠折扣")

    class Meta:
        db_table = "ly_course_price_dicount"
        verbose_name="课程与优惠策略的关系表"
        verbose_name_plural="课程与优惠策略的关系表"

    def __str__(self):
        return "课程：%s，优惠活动: %s,开始时间:%s,结束时间:%s" % (self.course.name, self.active.name, self.active.start_time,self.active.end_time)




class CourseExpire(BaseModel):
    """课程有效期模型"""
    # 后面必须在数据库把course和expire_time字段设置为联合索引
    course = models.ForeignKey("Course", related_name='course_expire', on_delete=models.CASCADE,
                               verbose_name="课程名称")
    expire_time = models.IntegerField(verbose_name="有效期", null=True, blank=True,help_text="有效期按天数计算")
    expire_text = models.CharField(max_length=150, verbose_name="提示文本", null=True, blank=True)
    price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程价格", default=0)

    class Meta:
        db_table = "ly_course_expire"
        verbose_name = "课程有效期"
        verbose_name_plural = verbose_name

    def __str__(self):
        return "课程：%s，有效期：%s，价格：%s" % (self.course, self.expire_text, self.price)



